home *** CD-ROM | disk | FTP | other *** search
- /* EasySound.c
-
- EEEEE AAA SSS Y Y SSS OOO U U N N DDD
- E A A S Y Y S O O U U NN N D D
- EEEE AAAAA SSS Y === SSS O O U U N N N D D
- E A A S Y S O O U U N NN D D
- EEEEE A A SSSS Y SSSS OOO UUU N N DDD
-
-
- EASY-SOUND V2.00 1990-09-23 ANDERS BJERIN
-
- AMIGA C CLUB (ACC)
- Anders Bjerin
- Tulevagen 22
- 181 41 LIDINGO
- SWEDEN
- */
-
-
-
- /* Include some important header files: */
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <devices/audio.h>
- #include <stdio.h>
-
-
- #define CLOCK_CONSTANT 3579545
- #define MUSIC_PRIORITY 0
-
-
- /* Structure containing all necessary information about the sound: */
- struct SoundInfo
- {
- BYTE *SoundBuffer; /* WaveForm Buffers */
- UWORD RecordRate; /* Record Rate */
- ULONG FileLength; /* WaveForm Lengths */
- };
-
-
- /* An IOAudio pointer to each sound channel: */
- struct IOAudio *IOA[ 4 ] = { NULL, NULL, NULL, NULL };
-
-
- typedef LONG Fixed;
- typedef struct
- {
- ULONG oneShotHiSamples; /* #samples in the high octave 1-shot part */
- ULONG repeatHiSamples; /* #samples in the high octave repeat part */
- ULONG samplesPerHiCycle; /* #samples/cycle in high octave, else 0 */
- UWORD samplesPerSec; /* Data sampling rate */
- UBYTE ctOctave; /* Number of octaves of waveforms */
- UBYTE sCompression; /* Data compression technique used */
- Fixed volume; /* Playback volume from 0 to 0x10000 */
- } Voice8Header;
-
-
- /* Declare the functions we are going to use: */
- CPTR PrepareSound();
- BOOL PlaySound();
- void StopSound();
- void RemoveSound();
-
- BOOL PrepareIOA();
- UWORD LoadSound();
- ULONG GetSize();
- ULONG SizeIFF();
- UWORD ReadIFF();
- BOOL MoveTo();
-
-
-
- /* PrepareSound() */
- /* PrepareSound() loads a sampled sound file (IFF or FutureSound) into */
- /* a buffer that is automatically allocated. All information about the */
- /* sound (record rate, length, buffersize etc) is put into an SoundInfo */
- /* structure. If PrepareSound() has successfully prepared the sound it */
- /* returns a pointer to a SoundInfo structure, otherwise it returns */
- /* NULL. */
- /* */
- /* Synopsis: pointer = PrepareSound( filename ); */
- /* pointer: (CPTR) Actually a pointer to a SoundInfo structure, but */
- /* since we do not want to confuse the user, we simply use a */
- /* normal memory pointer. */
- /* filename: (STRPTR) Pointer to a string containing the name of the */
- /* sound file. For example "df0:Explosion.snd". */
-
- CPTR PrepareSound( file )
- STRPTR file;
- {
- /* Declare a pointer to a SoundInfo structure: */
- struct SoundInfo *info;
-
- /* Allocate memory for a SoundInfo structure: (The memory can be of */
- /* any type, and should be cleared. */
- info = (struct SoundInfo *) AllocMem( sizeof( struct SoundInfo ),
- MEMF_PUBLIC|MEMF_CLEAR );
-
-
- if( info )
- {
- /* The memory have been successfully allocated. */
-
- /* Get the size of the file, and store it in the SoundInfo struct.: */
- if( info->FileLength = GetSize( file ) )
- {
- /* Allocate enough memory for the sampled sound, and store a */
- /* pointer to the buffer in the SoundInfo structure: */
- info->SoundBuffer = (BYTE *) AllocMem( info->FileLength,
- MEMF_CHIP|MEMF_CLEAR );
-
- if( info->SoundBuffer )
- {
- /* The memory have been successfully allocated. */
-
- /* Load the sound, and store the record rate in the SoundInfo */
- /* structure. If the sound could not be loaded, 0 is returned: */
- if( info->RecordRate = LoadSound( file, info ) )
- {
- /* OK! The sound has successfully been loaded. */
-
- /* Old FutureSound files were saved in kHz. If the record rate */
- /* is less than one hundered, we know it is an old FutureSound */
- /* file, and simply multiply the rate with one thousand: */
- if( info->RecordRate < 100 )
- info->RecordRate *= 1000;
-
- /* Return a pointer to the SoundInfo structure. (We return a */
- /* normal memory pointer.) */
- return( (CPTR) info ); /* OK! */
- }
- else
- {
- /* ERROR! We could not load the sound! */
-
- /* Deallocate the memory for the sound buffer: */
- FreeMem( info->SoundBuffer, info->FileLength );
- }
- }
- }
- /* Deallocate the memory the SoundInfo structure: */
- FreeMem( info, sizeof( struct SoundInfo ) );
- }
-
- /* We have not been able to prepare the sound. All allocated memory */
- /* have been deallocated, and we return NULL. */
- return( NULL ); /* ERROR! */
- }
-
-
-
- /* PlaySound() */
- /* PlaySound() plays one already prepared sound effect. You can decide */
- /* what volume, which channel should, what rate, and how many times the */
- /* sound should be played. */
- /* */
- /* Synopsis: ok = PlaySound( pointer, volume, channel, drate, times ); */
- /* ok: (BOOL) If the sound was played successfully TRUE is */
- /* returned, else FALSE. */
- /* pointer: (CPTR) Actually a pointer to a SoundInfo structure. This */
- /* pointer was returned by PrepareSound(). */
- /* volume: (UWORD) Volume, 0 to 64. */
- /* channel: (UBYTE) Which channel should be used. (LEFT0, RIGHT0, */
- /* RIGHT1 or LEFT1) */
- /* drate: (WORD) Delta rate. When the sound is prepared, the record */
- /* rate is automatically stored in the SoundInfo structure, */
- /* so if you do not want to change the rate, write 0. */
- /* times: (UWORD) How many times the sound should be played. If you */
- /* want to play the sound forever, write 0. (To stop a sound */
- /* call the function StopSound().) */
-
- BOOL PlaySound( info, volume, channel, delta_rate, repeat )
- struct SoundInfo *info;
- UWORD volume;
- UBYTE channel;
- WORD delta_rate;
- UWORD repeat;
- {
- /* Before we may play the sound, we must make sure that the sound is */
- /* not already being played. We will therefore call the function */
- /* StopSound(), in order to stop the sound if it is playing: */
- StopSound( channel );
-
- /* Call the PrepareIOA() function that will declare and initialize an */
- /* IOAudio structure: */
- if( PrepareIOA( CLOCK_CONSTANT / info->RecordRate + delta_rate, volume,
- repeat, channel, info ) )
- {
- /* We will now start playing the sound: */
- BeginIO( IOA[ channel ] );
- return( TRUE ); /* OK! */
- }
- else
- return( FALSE ); /* ERROR! */
- }
-
-
-
- /* StopSound() */
- /* StopSound() will stop the specified audio channel from continuing */
- /* to play the sound. It will also close all devices and ports that */
- /* have been opened, and deallocate some memory that have been */
- /* allocated. */
- /* */
- /* Synopsis: StopSound( channel ); */
- /* channel: (UBYTE) The audio channel that should be stopped. (LEFT0, */
- /* LEFT1, RIGHT0 or RIGHT1.) */
-
- void StopSound( channel )
- UBYTE channel;
- {
- /* Check if the IOAudio structure exist: */
- if( IOA[ channel ] )
- {
- /* 1. Stop the sound: */
- AbortIO( IOA[ channel ] );
-
- /* 2. If there exist a Sound Device, close it: */
- if( IOA[ channel ]->ioa_Request.io_Device )
- CloseDevice( IOA[ channel ] );
-
- /* 3. If there exist a Message Port, delete it: */
- if( IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort )
- DeletePort( IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort );
-
- FreeMem( IOA[ channel ], sizeof( struct IOAudio ) );
- IOA[ channel ] = NULL;
- }
- }
-
-
-
- /* RemoveSound() */
- /* RemoveSound() will stop playing the sound, and deallocate all memory */
- /* that was allocated by the PrepareSound() function. Before your */
- /* program terminates, all sound that has been prepared, MUST be */
- /* removed. */
- /* */
- /* IMPORTANT! The each channel that is currently playing the sound must */
- /* be stopped! (Use the StopSound() function.) */
-
- /* Synopsis: RemoveSound( pointer ); */
- /* pointer: (CPTR) Actually a pointer to a SoundInfo structure. */
-
- void RemoveSound( info )
- struct SoundInfo *info;
- {
- /* IMPORTANT! The sound must have been */
- /* stopped before you may remove it!!! */
-
- /* Have we allocated a SoundInfo structure? */
- if( info )
- {
- /* Deallocate the sound buffer: */
- FreeMem( info->SoundBuffer, info->FileLength );
-
- /* Deallocate the SoundInfo structure: */
- FreeMem( info, sizeof( struct SoundInfo ) );
- info = NULL;
- }
- }
-
-
-
- /* PrepareIOA() */
- /* PrepareIOA() allocates and initializes an IOAudio structure. */
- /* */
- /* Synopsis: ok = PrepareIOA( period, volume, cycles, channel, pointer ); */
- /* */
- /* ok: (BOOL) If the IOAudio structure was allocated and */
- /* initialized successfully, TRUE is returned, else FALSE. */
- /* period: (UWORD) Period time. */
- /* volume: (UWORD) Volume, 0 to 64. */
- /* cycles: (UWORD) How many times the sound should be played. */
- /* (0 : forever) */
- /* channel: (UBYTE) Which channel should be used. (LEFT0, RIGHT0, */
- /* RIGHT1 or LEFT1) */
- /* pointer: (CPTR) Actually a pointer to a SoundInfo structure. */
-
- BOOL PrepareIOA( period, volume, cycles, channel, info)
- UWORD period, volume, cycles;
- UBYTE channel;
- struct SoundInfo *info;
- {
- UBYTE ch;
-
- /* Declare a pointer to a MsgPort structure: */
- struct MsgPort *port;
-
- /* Allocate space for an IOAudio structure: */
- IOA[ channel ] = (struct IOAudio *) AllocMem( sizeof( struct IOAudio ),
- MEMF_PUBLIC|MEMF_CLEAR );
-
- /* Could we allocate enough memory? */
- if( IOA[ channel ] )
- {
- /* Create Message port: */
- if((port = (struct MsgPort *) CreatePort( "Sound Port", 0 )) == NULL)
- {
- /* ERROR! Could not create message port! */
- /* Deallocate the IOAudio structure: */
- FreeMem( IOA[ channel ], sizeof(struct IOAudio) );
- IOA[ channel ] = NULL;
-
- return( FALSE ); /* ERROR! */
- }
- else
- {
- /* Port created successfully! */
- /* Initialize the IOAudion structure: */
-
- /* Priority: */
- IOA[ channel ]->ioa_Request.io_Message.mn_Node.ln_Pri = MUSIC_PRIORITY;
-
- /* Port: */
- IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort = port;
-
- /* Channel: */
- ch = 1<<channel;
- IOA[ channel ]->ioa_Data = &ch;
-
- /* Length: */
- IOA[ channel ]->ioa_Length = sizeof( UBYTE );
-
- /* Open Audio Device: */
- if( OpenDevice( AUDIONAME, 0, IOA[ channel ], 0) )
- {
- /* ERROR! Could not open the device! */
- /* Delete Sound Port: */
- DeletePort( port );
-
- /* Deallocate the IOAudio structure: */
- FreeMem( IOA[ channel ], sizeof(struct IOAudio) );
- IOA[ channel ] = NULL;
-
- return( FALSE ); /* ERROR! */
- }
- else
- {
- /* Device opened successfully! */
- /* Initialize the rest of the IOAudio structure: */
- IOA[ channel ]->ioa_Request.io_Flags = ADIOF_PERVOL;
- IOA[ channel ]->ioa_Request.io_Command = CMD_WRITE;
- IOA[ channel ]->ioa_Period = period;
- IOA[ channel ]->ioa_Volume = volume;
- IOA[ channel ]->ioa_Cycles = cycles;
-
- /* The Audion Chip can of some strange reason not play sampled */
- /* sound that is longer than 131KB. So if the sound is to long, */
- /* we simply cut it off: */
- if( info->FileLength > 131000 )
- IOA[ channel ]->ioa_Length = 131000;
- else
- IOA[ channel ]->ioa_Length = info->FileLength;
-
- IOA[ channel ]->ioa_Data = info->SoundBuffer;
-
- return( TRUE ); /* OK! */
- }
- }
- }
- return( FALSE ); /* ERROR! */
- }
-
-
-
- /* LoadSound() */
- /* LoadSound() will load sampled sound that was either saved in IFF or */
- /* FutureSound format. */
- /* */
- /* Synopsis: rate = LoadSound( filename, pointer ); */
- /* rate: (UWORD) The record rate is returned if the sound was */
- /* successfully loaded, else 0. */
- /* filename: (STRPTR) Pointer to a string containing the name of the */
- /* sound file. For example "df0:Explosion.snd". */
- /* pointer: (CPTR) Actually a pointer to a SoundInfo structure. */
-
-
- UWORD LoadSound( filename, info )
- STRPTR filename;
- struct SoundInfo *info;
- {
- FILE *file_ptr; /* Pointer to a file. */
- ULONG length; /* Data Length. */
- UWORD record_rate; /* Record rate. */
-
-
- /* Check if it is an IFF File: */
- if( SizeIFF( filename ) )
- {
- /* Yes, it is an IFF file. Read it: */
- return( ReadIFF( filename, info ) );
- }
- else
- {
- /* No, then it is probably a FutureSound file. */
- /* Open the file so we can read it: */
- if( (file_ptr = fopen( filename, "r" )) == 0 )
- return( 0 ); /* ERROR! Could not open the file! */
-
- /* Read the data length: */
- if( fread( (char *) &length, sizeof( ULONG ), 1, file_ptr ) == 0 )
- {
- /* ERROR! Could not read the data length! */
- /* Close the file, and return zero: */
- fclose( file_ptr );
- return( 0 );
- }
-
- /* Read the record rate: */
- if( fread( (char *) &record_rate, sizeof( UWORD ), 1, file_ptr ) == 0 )
- {
- /* ERROR! Could not read the record rate! */
- /* Close the file, and return zero: */
- fclose( file_ptr );
- return( 0 );
- }
-
- /* Read the sampled sound data into the buffer: */
- if( fread( (char *) info->SoundBuffer, length, 1, file_ptr ) == 0 )
- {
- /* ERROR! Could not read the data! */
- /* Close the file, and return zero: */
- fclose( file_ptr );
- return( 0 );
- }
-
- /* Close the file: */
- fclose( file_ptr );
-
- /* Return the record rate: */
- return( record_rate );
- }
- }
-
-
-
-
- /* GetSize() */
- /* GetSize() returns the size of the file which was saved in either */
- /* IFF or FutureSound format. */
- /* */
- /* Synopsis: length = GetSize( filename ); */
- /* length: (ULONG) Data length. */
- /* filename: (STRPTR) Pointer to a string containing the name of the */
- /* sound file. For example "df0:Explosion.snd". */
-
- ULONG GetSize( filename )
- STRPTR filename;
- {
- FILE *file_ptr; /* Pointer to a file. */
- ULONG length; /* Data length. */
-
-
- /* Check if it is an IFF File: */
- if( ( length = SizeIFF( filename ) ) == 0 )
- {
- /* No, then it is probably a FutureSound file. */
- /* Open the file so we can read it: */
- if( ( file_ptr = fopen( filename, "r" ) ) == 0 )
- return( 0 ); /* ERROR! Could not open the file! */
-
- /* Read the data length: */
- if( fread( (char *) &length, sizeof( ULONG ), 1, file_ptr ) == 0)
- {
- /* ERROR! Could not read the data length! */
- /* Close the file, and return zero: */
- fclose( file_ptr );
- return( 0 );
- }
-
- /* Close the file: */
- fclose( file_ptr );
- }
- return( length );
- }
-
-
-
- /* SizeIFF() */
- /* SizeIFF() returns the size of an IFF file, or zero if something */
- /* went wrong (for example, It was not an IFF file). */
- /* */
- /* Synopsis: length = SizeIFF( filename ); */
- /* length: (ULONG) Data length. */
- /* filename: (STRPTR) Pointer to a string containing the name of the */
- /* IFF file. For example "df0:Explosion.snd". */
-
- ULONG SizeIFF( filename )
- STRPTR filename;
- {
- FILE *file_ptr; /* Pointer to a file. */
- STRPTR empty_string = " "; /* Four spaces. */
- LONG dummy; /* A dummy variable. */
- Voice8Header Header; /* Voice8Header structure. */
-
-
- /* Try to open the file: */
- if( file_ptr = fopen( filename, "r" ) )
- {
- fread( (char *) empty_string, 4, 1, file_ptr );
- if( strcmp( empty_string, "FORM" ) == 0)
- {
- /* Read twice: */
- fread( (char *) empty_string, 4, 1, file_ptr );
- fread( (char *) empty_string, 4, 1, file_ptr );
-
- /* Check if it is a "8SVX" file, or not: */
- if( strcmp( empty_string, "8SVX" ) == 0 )
- {
- MoveTo( "VHDR", file_ptr );
- fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
- fread( (char *) &Header, sizeof( Header ), 1, file_ptr );
-
- /* Close the file, and return the length: */
- fclose( file_ptr );
- return( Header.oneShotHiSamples + Header.repeatHiSamples );
- }
- }
- /* Close the file: */
- fclose( file_ptr );
- }
- /* Return zero: (ERROR) */
- return( 0 );
- }
-
-
-
- /* ReadIFF() */
- /* ReadIFF() reads an IFF file into the buffer, and returns the record */
- /* rate. */
- /* */
- /* Synopsis: rate = ReadIFF( filename, pointer ); */
- /* rate: (UWORD) The record rate is returned if the sound was */
- /* successfully loaded, else 0. */
- /* filename: (STRPTR) Pointer to a string containing the name of the */
- /* sound file. For example "df0:Explosion.snd". */
- /* pointer: (CPTR) Actually a pointer to a SoundInfo structure. */
-
- UWORD ReadIFF( filename, info )
- STRPTR filename;
- struct SoundInfo *info;
- {
- FILE *file_ptr; /* Pointer to a file. */
- STRPTR empty_string = " "; /* Four spaces. */
- LONG dummy; /* A dummy variable. */
- Voice8Header Header; /* Voice8Header structure. */
-
-
- /* Try to open the file: */
- if( file_ptr = fopen( filename, "r" ) )
- {
- fread( (char *) empty_string, 4, 1, file_ptr );
- if( strcmp( empty_string, "FORM" ) == 0 )
- {
- /* Read twice: */
- fread( (char *) empty_string, 4, 1, file_ptr );
- fread( (char *) empty_string, 4, 1, file_ptr );
-
- /* Check if it is a "8SVX" file, or not: */
- if( strcmp( empty_string, "8SVX" ) == 0 )
- {
- MoveTo( "VHDR", file_ptr );
- fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
- fread( (char *) &Header, sizeof( Header ), 1, file_ptr );
-
- MoveTo( "BODY", file_ptr );
- fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
- fread( (char *) info->SoundBuffer, Header.oneShotHiSamples +
- Header.repeatHiSamples, 1, file_ptr );
-
- /* Close the file, and return the record rate: */
- fclose( file_ptr );
- return( Header.samplesPerSec );
- }
- }
- /* Close the file: */
- fclose( file_ptr );
- }
- /* Return zero: (ERROR) */
- return( 0 );
- }
-
-
-
- /* MoveTo() */
- /* MoveTo() walks through an IFF file, and looks for chunks. */
- /* */
- /* Synopsis: MoveTo( chunk, file_ptr ); */
- /* chunk: (STRPTR) The chunk we want to get to. */
- /* file_ptr: (FILE *) Pointer to an already opened file. */
-
- BOOL MoveTo( check_string, file_ptr )
- STRPTR check_string;
- FILE *file_ptr;
- {
- STRPTR empty_string = " "; /* Four spaces. */
- int skip, loop; /* How much data should be skiped. */
- LONG dummy; /* A dummy variable. */
-
-
- /* As long as we have not reached the EOF, continue: */
- while( !feof( file_ptr ) )
- {
- fread( (char *) empty_string, 4, 1, file_ptr);
-
- /* Have we found the right chunk? */
- if( strcmp( check_string, empty_string ) ==0 )
- return( 0 ); /* YES! Return nothing. */
-
- /* Move foreward: */
- fread( (char *) &skip, sizeof( LONG ), 1, file_ptr );
- for( loop = 0; loop < skip; loop++ )
- fread( (char *) &dummy, 1, 1, file_ptr);
- }
- }
-